package com.jiexin.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.jiexin.beans.CacheKeyConstants;
import com.jiexin.common.RequestHolder;
import com.jiexin.dao.SysAclMapper;
import com.jiexin.dao.SysRoleAclMapper;
import com.jiexin.dao.SysRoleUserMapper;
import com.jiexin.model.SysAcl;
import com.jiexin.model.SysUser;
import com.jiexin.util.JsonMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author: Jay_Liu
 * @Description:
 * @Date: Created in 13:15 2018/4/21 0021
 * @Modified By:
 */
@Service
public class SysCoreService {

    @Resource
    SysAclMapper sysAclMapper;

    @Resource
    SysRoleUserMapper sysRoleUser;

    @Resource
    SysRoleAclMapper sysRoleAclMapper;

    @Resource
    SysCacheService sysCacheService;

    //获取当前用户的权限列表
    public List<SysAcl> getCurrentUserAclList () {
        Integer userId = RequestHolder.getCurrentUser().getId();
        List<SysAcl> userAclList = getUserAclList(userId);
        return userAclList;
    }

    //获取当前角色权限列表
    public List<SysAcl> getCurrentRoleAclList (int roleId) {
        List<Integer> aclListByRoleIdList = sysRoleAclMapper.getAclIdListByRoleIdList(Lists.newArrayList(roleId));
        if (CollectionUtils.isEmpty(aclListByRoleIdList)) {
            return Lists.newArrayList();
        }
        return sysAclMapper.getAclListByIdList(aclListByRoleIdList);
    }

    public List<SysAcl> getUserAclList (int userId) {
        if (isSuperAdmin()) {
            return sysAclMapper.getAllAcl();
        }
        //通过用户id获取其角色id集合
        List<Integer> roleIdList = sysRoleUser.getRoleIdListByUserId(userId);
        if (CollectionUtils.isEmpty(roleIdList)) {
            return Lists.newArrayList();
        }
        //通过角色id集合获取权限id集合
        List<Integer> aclIdList = sysRoleAclMapper.getAclIdListByRoleIdList(roleIdList);
        if (CollectionUtils.isEmpty(aclIdList)) {
            return Lists.newArrayList();
        }
        return sysAclMapper.getAclListByIdList(aclIdList);
    }

    //是否是超级管理员，则代表拥有所有权限
    public boolean isSuperAdmin () {
        //根据实际项目需要定义超级管理员
        //1.指定用户 或者指定角色，或者指定邮箱，或者根据数据库字段或者配置文件
        SysUser currentUser = RequestHolder.getCurrentUser();
        List<Integer> roleIdList = sysRoleUser.getRoleIdListByUserId(currentUser.getId());
        Set<Integer> roleIdSet = Sets.newHashSet(roleIdList);
        //4为“超级管理员”ID，ID不可改，角色名称可以改，这里以ID来判端
        if(currentUser.getUsername().equalsIgnoreCase("Admin") || roleIdSet.contains(4)){
            return true;
        }
        return false;
    }

    /**
     * 是否有对应URL的访问权限
     * @param url 访问地址
     * @return
     */
    public boolean hasUrlAcl(String url) {
        if(isSuperAdmin()) {
            return true;
        }
        List<SysAcl> aclList = sysAclMapper.getAclByUrl(url);
        //若系统中权限没有控制改地址，则放过
        if(CollectionUtils.isEmpty(aclList)) {
            return true;
        }
        //是否都是无效权限
        boolean isNotAllInvalid = false;
        //从Cache中获取当前用户的权限点
        List<SysAcl> currentUserAclList = getCurrentUserAclFromCache();
        Set<Integer> currentUserAclIdList = currentUserAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
        for (SysAcl sysAcl : aclList) {
            if (sysAcl == null || sysAcl.getStatus() != 1) {
                continue;
            }
            isNotAllInvalid =true;
            //判断用户中的权限存在一个拥有该URL的访问权限
            if(currentUserAclIdList.contains(sysAcl.getId())){
                return true;
            }
        }
        //若都是无效的路径控制的则表示失效的，则可以访问
        if(!isNotAllInvalid) {
            return true;
        }
        return false;
    }

    public List<SysAcl> getCurrentUserAclFromCache() {
        int userId = RequestHolder.getCurrentUser().getId();
        String userAclsfromCache = sysCacheService.getFromCache(CacheKeyConstants.USER_ACLS, String.valueOf(userId));
        if (StringUtils.isBlank(userAclsfromCache)) {
            List<SysAcl> userAclList = getUserAclList(userId);
            if (CollectionUtils.isNotEmpty(userAclList)) {
                sysCacheService.saveCache(JsonMapper.obj2String(userAclList), 600, CacheKeyConstants.USER_ACLS, String.valueOf(userId));
            }
            return userAclList;
        }
        return JsonMapper.string2Obj(userAclsfromCache, new TypeReference<List<SysAcl>>() {
        });
    }
}
